package com.shanks.home.module.network;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;

import org.json.JSONException;
import org.json.JSONObject;

import com.shanks.home.model.GameData;
import com.shanks.home.model.RoomData;
import com.shanks.home.model.SocketCommand;
import com.shanks.home.net.HttpResponser;
import com.shanks.home.net.HttpService;
import com.shanks.home.net.SocketByteHashMap;
import com.shanks.home.net.SocketCommandBody;
import com.shanks.home.net.SocketCommandHeader;
import com.shanks.home.net.SocketResponser;
import com.shanks.home.net.SocketService;
import com.shanks.home.util.LogUtil;
import com.shanks.home.util.NetUtil;

/**
 * @author Shanks
 * @time 2013.01.03
 */
public class SocketModule {
	
	private static String TAG = SocketModule.class.getSimpleName();
	private Thread socketThread = null;
	private SocketService socketService;

	public void enterRoom() {
		prepareLoginRoom();
	}

	private void prepareLoginRoom() {
		HttpService.beginPOST();
		HttpService.addParameter("mod", "table");
		HttpService.addParameter("act", "quickIn");
		HttpService.setResponder(httpResponser);
		HttpService.asyncRequest();
	}
	
	private HttpResponser httpResponser = new HttpResponser() {

		@Override
		public void onFailure(Throwable arg0, String arg1) {
			
		}

		@Override
		public void onSuccess(int arg0, String arg1) {
			quickInHandler(arg1);
		}
	};
	
	private void quickInHandler(String data) {
		JSONObject obj;
		try {
			obj = new JSONObject(data);
			RoomData.ip = obj.getString("ip");
			RoomData.port = Integer.parseInt(obj.getString("port"));
			RoomData.tid = obj.getInt("tid");

			connectServer();
		} catch (JSONException e) {
			e.printStackTrace();
		}
	}
	
	public void connectServer() {
		if (socketThread != null) {
			if (!socketThread.isInterrupted()) {
				socketThread.interrupt();
			}
			socketThread = null;
		}
		socketThread = new Thread("socketThread") {
			public void run() {
				if (!Thread.currentThread().isInterrupted()) {
					try {
						Thread.sleep(200);
					} catch (InterruptedException e) {
						
					}

					if (socketService == null) {
						socketService = new SocketService(socketResponser);
						try {
							socketService.Connect(GameData.proxyIp, GameData.proxyPort);
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}					
					
					requestEnterRoom();
				}
			}
		};
		socketThread.start();
	}

	public void requestEnterRoom() {
		short command = SocketCommand.CLI_CMD_LOGIN;
		short version = SocketCommand.CLI_CMD_LOGIN_VER;

		byte tid = 1; 
		byte uid = 2;
		byte mtkey = 3;
		byte imgUrl = 4;
		byte giftId = 5;
		
		SocketByteHashMap hashMap = new SocketByteHashMap();
		hashMap.putInt(tid, 10012);
		hashMap.putInt(uid, GameData.uid);
		hashMap.putString(mtkey, GameData.mtkey.getBytes());
		hashMap.putString(imgUrl, GameData.smallImgUrl.getBytes());
		hashMap.putInt(giftId, 0);

		
		
		byte[] body = SocketCommandBody.encode(command, hashMap);
		byte[] header = encodeHeader(command, version, (short) body.length);
		sendCommand(header, body);
	}
	
	public byte[] encodeHeader(short cmd, short version, short bodySize){
		SocketByteHashMap hashBody = new SocketByteHashMap();
		
		byte Flag		= 1;
		byte Cmd		= 2;
		byte Version 	= 3;
		byte BodyLength = 4;
		hashBody.putString(Flag, SocketCommand.HEADER_START_FLAG.getBytes());
		hashBody.putShort(Cmd, cmd);
		hashBody.putShort(Version, version);
		hashBody.putShort(BodyLength, bodySize);
		
		byte[] result = null;
		try{
			result = SocketCommandHeader.encode(hashBody);
		}
		catch (Exception e) {
			result = null;
		}
		
		return result;
	}
	
	public void sendCommand(byte[] header, byte[] body) {
		int total = 0;		
		if (header != null) {
			total = header.length;
		}
		if (body != null) {
			total += body.length;
		}
		
		ByteBuffer buffer = ByteBuffer.allocate(total);
		if (header != null) {
			buffer.put(header);
		}
		if (body != null) {
			buffer.put(body);
		}
		
		byte[] data = buffer.array();
		try {
			String str1 = "";
			String str2 = "";
			for (int i = 0; i < data.length; i ++) {
				str1 += String.valueOf((data[i])) + ":";
				str2 += String.valueOf(Integer.toHexString(data[i])) + ":";
			}
			LogUtil.i(TAG, "send socket data(10进制):" + str1);
			LogUtil.i(TAG, "send socket data(16进制):" + str2);
			
			socketService.send(data, data.length);
		} catch (IOException e) {
			
		}
		
		buffer.clear();
		buffer = null;
	}
	
	private SocketResponser socketResponser = new SocketResponser() {
		
		@Override
		public void onReceive(InputStream is) throws Exception {
			// TODO Auto-generated method stub
			byte[] 	head = new byte[SocketCommandHeader.HEADER_SIZE];
			byte[] 	body = null;
			
			// read head
			int expectedReadLen = head.length;
			do {
				try {
					int readLen;
					readLen = is.read(head, head.length - expectedReadLen, expectedReadLen);
					expectedReadLen -= readLen;
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} while(expectedReadLen > 0);
			
			// read body
			SocketByteHashMap hashHeader = SocketCommandHeader.decode(head);
			short command = 0;			
			byte BodyLength = 4;
			byte Cmd		= 2;
			if (hashHeader == null) {
				
			} else {
				int len = NetUtil.shortToUnsignedInt(hashHeader.getShort(BodyLength));
				if (len < 0 || len > 163840) {
					
				}
				command = hashHeader.getShort(Cmd);
				
				body = new byte[len];
				if (len > 0) {
					expectedReadLen = len;
					do {
						int readLen = is.read(body, len - expectedReadLen, expectedReadLen);
						expectedReadLen -= readLen;
					} while(expectedReadLen > 0);
					
					String str1 = "";
					String str2 = "";
					for (int i = 0; i < body.length; i ++) {
						str1 += String.valueOf((body[i])) + ":";
						str2 += String.valueOf(Integer.toHexString(body[i])) + ":";
					}
					LogUtil.i(TAG, "get socket data(10进制):command:" + command + "---data:" + str1);
					LogUtil.i(TAG, "get socket data(16进制):command:" + Integer.toHexString(command) + "---data:" + str2);
				} else {
					LogUtil.i(TAG, "get socket data(10进制):command:" + command);
					LogUtil.i(TAG, "get socket data(16进制):command:" + Integer.toHexString(command));
				}
			}
		}
	};
	
}